package com.kmxd.ams.app.use;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kmxd.ams.client.archive.IArchiveAuthSvc;
import com.kmxd.ams.client.archive.IArchiveTypeSvc;
import com.kmxd.ams.client.archive.vo.ArchiveAuthScopeVO;
import com.kmxd.ams.client.archive.vo.ArchiveTypeVO;
import com.kmxd.ams.client.arrange.IBoxSvc;
import com.kmxd.ams.client.arrange.IDocumentSvc;
import com.kmxd.ams.client.arrange.IVolumeSvc;
import com.kmxd.ams.client.system.ISysFondsSvc;
import com.kmxd.ams.client.use.IUseBorrowCarSvc;
import com.kmxd.ams.client.use.IUseFavoritesSvc;
import com.kmxd.ams.client.use.IUsePushDetailSvc;
import com.kmxd.ams.client.use.IUsePushSvc;
import com.kmxd.ams.client.use.dto.*;
import com.kmxd.ams.client.use.vo.*;
import com.kmxd.ams.core.common.constant.ErrorCode;
import com.kmxd.ams.core.common.enums.UsePushStatusEnum;
import com.kmxd.ams.core.exception.BizTipException;
import com.kmxd.ams.core.util.IdUtil;
import com.kmxd.ams.core.util.SecurityUtil;
import com.kmxd.ams.infra.arrange.entity.Box;
import com.kmxd.ams.infra.arrange.entity.Document;
import com.kmxd.ams.infra.arrange.entity.Volume;
import com.kmxd.ams.infra.system.entity.SysFonds;
import com.kmxd.ams.infra.tmpl.dto.ArchTmplBO;
import com.kmxd.ams.infra.use.entity.UsePushDetail;
import com.kmxd.ams.infra.use.mapper.UsePushDetailMapper;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import org.apache.commons.compress.utils.Lists;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 推送档案表 服务实现类
 *
 * @author nickbi
 * @since 2023-01-11
 */
@Service
@AllArgsConstructor
public class UsePushDetailSvcImpl extends ServiceImpl<UsePushDetailMapper, UsePushDetail>
    implements IUsePushDetailSvc {

  private UsePushDetailMapper usePushDetailMapper;

  @Override
  public Page<UsePushDetailListVO> selectPage(Page reqPage, UsePushDetailQueryDTO req) {
    LambdaQueryWrapper<UsePushDetail> wrapper = buildQuery(req);
    Page<UsePushDetail> page = usePushDetailMapper.selectPage(reqPage, wrapper);
    Page<UsePushDetailListVO> voPage = BeanUtil.copyProperties(page, Page.class);
    voPage.setRecords(convert(page.getRecords()));
    return voPage;
  }

  private List<UsePushDetailListVO> convert(List<UsePushDetail> list) {
    if (ObjectUtil.isEmpty(list)) {
      return Lists.newArrayList();
    }
    return list.stream()
        .map(
            detail -> {
              UsePushDetailListVO vo = setArchInfo(detail);
              // 借阅车
              setBorrowCarFlag(vo);
              setFavoritesFlag(vo);
              setFondsName(vo);
              setArchTypeName(vo);
              setAuthType(vo);
              return vo;
            })
        .collect(Collectors.toList());
  }

  private void setFondsName(UsePushDetailListVO vo) {
    ISysFondsSvc fondsSvc = SpringUtil.getBean(ISysFondsSvc.class);
    SysFonds fonds = Optional.ofNullable(fondsSvc.getById(vo.getFondsId())).orElse(new SysFonds());
    vo.setFondsName(fonds.getName());
  }

  private void setArchTypeName(UsePushDetailListVO vo) {
    IArchiveTypeSvc archiveTypeSvc = SpringUtil.getBean(IArchiveTypeSvc.class);
    ArchiveTypeVO archiveTypeVO =
        Optional.of(archiveTypeSvc.view(vo.getArchTypeId())).orElse(new ArchiveTypeVO());
    vo.setArchTypeName(archiveTypeVO.getName());
  }

  private void setAuthType(UsePushDetailListVO vo) {
    IArchiveAuthSvc bean = SpringUtil.getBean(IArchiveAuthSvc.class);
    ArchiveAuthScopeVO archiveAuthVO =
        Optional.ofNullable(bean.getByArchTypeId(vo.getArchTypeId()))
            .orElse(new ArchiveAuthScopeVO());
    // todo... 知悉范围重构
    //    vo.setAuthType(archiveAuthVO.getAuthType());
  }

  private UsePushDetailListVO setArchInfo(UsePushDetail detail) {
    UsePushDetailListVO vo = BeanUtil.copyProperties(detail, UsePushDetailListVO.class);

    if (CharSequenceUtil.equals(detail.getTableId(), ArchTmplBO.DOCUMENT)) {
      IDocumentSvc documentSvc = SpringUtil.getBean(IDocumentSvc.class);
      Document qryDoc = new Document();
      qryDoc.setArchTypeId(detail.getArchTypeId());
      qryDoc.setTableId(detail.getTableId());
      qryDoc.setId(detail.getArchId());
      Document view = documentSvc.view(qryDoc);
      vo.setArchCode(view.getArchCode());
      vo.setArchTitle(view.getTitle());
      vo.setYear(view.getYear());
      vo.setSecurity(view.getSecurity());
      vo.setFillingNum(view.getFillingNum());
      vo.setFilesNum(view.getFilesNum());
    }
    if (CharSequenceUtil.equals(detail.getTableId(), ArchTmplBO.VOLUME)) {
      IVolumeSvc volumeSvc = SpringUtil.getBean(IVolumeSvc.class);
      Volume qryDoc = new Volume();
      qryDoc.setArchTypeId(detail.getArchTypeId());
      qryDoc.setTableId(detail.getTableId());
      qryDoc.setId(detail.getArchId());
      Volume view = volumeSvc.view(qryDoc);
      vo.setArchCode(view.getArchCode());
      vo.setArchTitle(view.getTitle());
      vo.setYear(view.getYear());
      vo.setSecurity(view.getSecurity());
      vo.setFillingNum(view.getFillingNum());
      vo.setFilesNum(view.getFilesNum());
    }
    if (CharSequenceUtil.equals(detail.getTableId(), ArchTmplBO.BOX)) {
      IBoxSvc boxSvc = SpringUtil.getBean(IBoxSvc.class);
      Box qryDoc = new Box();
      qryDoc.setArchTypeId(detail.getArchTypeId());
      qryDoc.setTableId(detail.getTableId());
      qryDoc.setId(detail.getArchId());
      Box view = boxSvc.view(qryDoc);
      vo.setArchTitle(view.getBoxNo());
      vo.setYear(view.getYear());
      vo.setSecurity(view.getSecurity());
      vo.setFilesNum(view.getFilesNum());
    }

    return vo;
  }

  private void setBorrowCarFlag(UsePushDetailListVO vo) {
    UseBorrowCarQueryDTO qryBorrowCar = new UseBorrowCarQueryDTO();
    qryBorrowCar.setTableId(vo.getTableId());
    qryBorrowCar.setArchTypeId(vo.getArchTypeId());
    qryBorrowCar.setArchId(vo.getArchId());
    UseBorrowCarVO borrowCar =
        SpringUtil.getBean(IUseBorrowCarSvc.class).getBorrowCar(qryBorrowCar);
    vo.setBorrowCarFlag(ObjectUtil.isNotNull(borrowCar));
  }

  private void setFavoritesFlag(UsePushDetailListVO vo) {
    // 设置收藏标识
    UseFavoritesQueryDTO qryFavorites = new UseFavoritesQueryDTO();
    qryFavorites.setTableId(vo.getTableId());
    qryFavorites.setArchTypeId(vo.getArchTypeId());
    qryFavorites.setArchId(vo.getArchId());
    UseFavoritesVO favorites =
        SpringUtil.getBean(IUseFavoritesSvc.class).getFavorites(qryFavorites);
    vo.setCollectFlag(ObjectUtil.isNotNull(favorites));
  }

  @Override
  public List<UsePushDetailListVO> selectList(UsePushDetailQueryDTO req) {
    LambdaQueryWrapper<UsePushDetail> wrapper = buildQuery(req);
    List<UsePushDetail> list = usePushDetailMapper.selectList(wrapper);
    return convert(list);
  }

  @Override
  public List<UsePushDetailListVO> selectUserList(UsePushDetailQueryDTO req) {
    IUsePushSvc usePushSvc = SpringUtil.getBean(IUsePushSvc.class);

    UsePushVO vo =
        Optional.ofNullable(usePushSvc.viewPush(req.getPushId(), SecurityUtil.getUserId()))
            .orElseThrow(() -> BizTipException.instance(ErrorCode.USE_PUSH_IS_NULL, "未找到该推送"));
    if (!ObjectUtil.equals(UsePushStatusEnum.PUSHED.getCode(), vo.getStatus())) {
      return Lists.newArrayList();
    }
    List<UsePushDetail> list =
        usePushDetailMapper.selectList(
            Wrappers.<UsePushDetail>lambdaQuery()
                .eq(UsePushDetail::getPushId, req.getPushId())
                .like(
                    CharSequenceUtil.isNotBlank(req.getArchTitle()),
                    UsePushDetail::getArchTitle,
                    req.getArchTitle()));
    return BeanUtil.copyToList(list, UsePushDetailListVO.class);
  }

  private LambdaQueryWrapper<UsePushDetail> buildQuery(UsePushDetailQueryDTO req) {
    return Wrappers.<UsePushDetail>lambdaQuery()
        .eq(ObjectUtil.isNotNull(req.getPushId()), UsePushDetail::getPushId, req.getPushId())
        .in(StrUtil.isNotBlank(req.getIds()), UsePushDetail::getId, IdUtil.split(req.getIds()));
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void add(UsePushDetailAddDTO req) {
    UsePushDetail entity = BeanUtil.copyProperties(req, UsePushDetail.class);
    usePushDetailMapper.insert(entity);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void edit(UsePushDetailEditDTO req) {
    UsePushDetail entity = BeanUtil.copyProperties(req, UsePushDetail.class);
    usePushDetailMapper.updateById(entity);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void remove(String ids) {
    Set<Long> idList = IdUtil.split(ids);
    this.baseMapper.deleteBatchIds(idList);
  }

  @Override
  public UsePushDetailVO view(Long id) {
    UsePushDetail entity = usePushDetailMapper.selectById(id);
    return BeanUtil.copyProperties(entity, UsePushDetailVO.class);
  }
}
